package ink.metoo.gude.module.websocket.config

import ink.metoo.gude.model.TopicConst
import ink.metoo.gude.module.websocket.interceptor.JwtAuthenticationChannelInterceptor
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.messaging.Message
import org.springframework.messaging.simp.config.ChannelRegistration
import org.springframework.messaging.simp.config.MessageBrokerRegistry
import org.springframework.messaging.support.ChannelInterceptor
import org.springframework.security.authorization.AuthorizationManager
import org.springframework.security.config.annotation.web.socket.EnableWebSocketSecurity
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
import org.springframework.web.socket.config.annotation.StompEndpointRegistry
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer

@Configuration
@EnableWebSocketMessageBroker
@EnableWebSocketSecurity
class WebSocketConfig(
    private val jwtChannelInterceptor: JwtAuthenticationChannelInterceptor,
) : WebSocketMessageBrokerConfigurer {

    override fun configureMessageBroker(registry: MessageBrokerRegistry) {
        registry.enableSimpleBroker("/topic")
        registry.setApplicationDestinationPrefixes("/app")
    }

    override fun registerStompEndpoints(registry: StompEndpointRegistry) {
        registry.addEndpoint("/cr")
            .setAllowedOriginPatterns("*")
            .withSockJS()
    }

    override fun configureClientInboundChannel(registry: ChannelRegistration) {
        registry.interceptors(jwtChannelInterceptor)
    }

    @Bean
    fun authorizationManager(builder: MessageMatcherDelegatingAuthorizationManager.Builder): AuthorizationManager<Message<*>> =
        builder
            .simpSubscribeDestMatchers(TopicConst.PRIVATE_TOPIC, TopicConst.PRIVATE_TOPIC).authenticated()
            .simpSubscribeDestMatchers(TopicConst.PUBLIC_TOPIC, TopicConst.ERROR_TOPIC).permitAll()
            .anyMessage().permitAll()
            .build()


    /**
     * 无效的csrf拦截器
     */
    @Bean
    fun csrfChannelInterceptor() = object : ChannelInterceptor {
    }

}